package VCS;
use strict;
use warnings;
use Data::Dumper;
use File::Path;
use Cwd;


# Export the public subroutines to programs that use this module 
BEGIN {
	require Exporter;
	our @ISA = qw(Exporter);
	our @EXPORT = qw();
	
}

my $usr; #svn username
my %f_hash; #hash with the revisions changes
my $build_tool_directory; 
my $vcs_path; 

###############################################################################
# Function: checkOutBuildParams
# This subroutine checks out the buildParams from the repository
#
# Inputs: buildParamsPath
# Returns: buildParams
###############################################################################

sub checkOutBuildParams{
	my $buildParamsPath = $_[1];
	my $buildParams;
	
	system("svn export $buildParamsPath");
	if($buildParamsPath =~ /buildParams\//){
		$buildParams = substr($buildParamsPath,"@+");
	}
return $buildParams;
}

###############################################################################
# Function: checkOutRelHis
# This subroutine gets the files in the tags folder to obtain the
# release history file, if it exists.
#
# Inputs: Tags path, svn username
# Returns: Nothing.  
###############################################################################

sub checkOutRelHis {
	$build_tool_directory = getcwd();
    $vcs_path = $_[1];
	my $username = $_[2];
	# --depth files will get just the files in tags folder
	system("svn checkout --depth files $vcs_path --username $username");    
}

###############################################################################
# Function: getBuildInfo
# This subroutine will export the specified file.
#
# Inputs: File path.
# Returns: Nothing.  
###############################################################################

sub getBuildInfo {	
	my $path = $_[1];
	system "svn export $path"; 
}

###############################################################################
# Function: getFileList
# This subroutine returns a list of all added,modified and deleted files
#
# Example of the hash returned format:
#
# file1.c => [10,M]
# file2.c => [5,A]
# file1.h => [10,D]
#
# Inputs: Current revision, repository path
# Returns: Reference to Files->revision,status hash  
###############################################################################

sub getFileList
{
	my $cur_rev = $_[1];
	my $path = $_[2];
	my $revMinus = $cur_rev - 1;
	my @fileList = ();
	my @stList = ();
	my $status;
	#Get the difference between the  current revision and the past revision
   my $cmd = "svn diff -r $revMinus:$cur_rev --summarize $path |";
    open(CMD, $cmd);
	while(my $line = <CMD>)
	{
		#Look at Modified (M), Deleted (D) or Added (A) files
		if($line =~ /^\s*M{1,2}\s+(.+)/) {	
			$status = "M";
		}
		if($line =~ /^\s*A\s+(.+)/) {		
			$status = "A";
		}
		if($line =~ /^\s*D\s+(.+)/) {	
			$status = "D";
		}
		#Add the status			
		push(@fileList, "$1");
		push(@stList, $status);		
	}	
	close(CMD);

	my @temp_file = ();
    #See if that revision already exists and insert the greater one
	for(my $i = 0; $i < scalar(@fileList);$i++){		
		if(exists $f_hash {$fileList[$i]})
		{
			my @rev = $f_hash{$fileList[$i]};		
			if($cur_rev > $rev[0][0])
			{
				delete $f_hash{$fileList[$i]};
				push @{$f_hash{$fileList[$i]}},$cur_rev, $stList[$i];
			}
			
		}
		else {	
		push @{$f_hash{$fileList[$i]}},$cur_rev, $stList[$i];
		}
	}

return \%f_hash;	
}

###############################################################################
# Function: createWorkCopy
#  This subroutine creates a working copy of the repository and then deletes 
# the files. The tool needs to create the working copy because without that, 
# the svn is not possible to do the svn copy after exporting the files. 
#
# Inputs: Trunk path.
# Returns: Nothing.  
###############################################################################

sub createWorkCopy{
	my $path = $_[1];
	#Checkout
	system "svn checkout $path";
	#Get current directory
	my $cur_dir = getcwd();
	#Go to the trunk
	chdir("trunk");
	#List just directories and delete everything
	my @del_dir;
	open(CMD,"ls -d * |");
	while(my $dir = <CMD>){
		chomp($dir);
		push(@del_dir,$dir);
	}
	close CMD;

	#Remove the directory trees
	foreach my $key(@del_dir){
		rmtree($key);	
	}
}

###############################################################################
# Function: exportFiles
# This subroutine gets the file path, removes the http:// and all folders before
# until (and including) trunk. Then it creates the file directories,
# to finally export the file inside the correct folder.
#
# Inputs: Repository path of the file 
# Returns: build tool path  
###############################################################################

 sub exportFiles{
 	#File revision
	my $rev = $_[1];
	#Repository file path
	my $rep_file = $_[2];
	#Local file path
	my $local_file;
	#Remove the http://
	if ($rep_file =~ /\/\//){
 		$local_file = substr $rep_file, "@+";
 		if($local_file =~ /trunk/){
 			#Remove trunk and everything before it from the path
 			$local_file = substr $local_file, "@+"+1;
            #Match starting from the end to remove the file and stay only with its directories
            if($local_file =~ /(.*)\//){
            	$local_file = "$1";
            }
 			#Create the directories
 			system "mkdir -p $local_file";
 		}
 		else {
 			die "Couldn't create directories $local_file";
 		}
 		
	}
	else {
		die "Couldn't create directories $local_file";
	}
	#Export file
	system "svn export -r $rev $rep_file $local_file";
return $build_tool_directory;
}


###############################################################################
# Function: tagBuild
#  This subroutine adds the files with "?" status, creates the build tag depending
# on the build type and number, to finally copy the files into the tags directory.
# 
#
# Inputs: Svn path, build type, build number, trunk directory
# Returns: Nothing
###############################################################################

sub tagBuild{
	
	my $svn_path = $_[1];
	my $build_type = $_[2];
	my $build_number = $_[3];
	my $trunk_directory = $_[4];
	my $rel_tag;
	
	$build_tool_directory = getcwd();
	#Enter the directory above code folder
	chdir($trunk_directory);
	print "\n--------------------------------------------------------------\n";
	print "\n                        TAGGING FILES                          \n";
	print "\n--------------------------------------------------------------\n";
	#Get all of files with the "?" status and do the svn add (sometimes the svn doesn't recognize automatically
	# that the file was added). Otherwise the tool will not be able to do the svn copy later.
	open(CMD, "svn stat | grep \"^?\"|");
	while(my $svn_add_param = <CMD>)
	{
	#If the svn didn't recognized the added files, the $svn_add_param will not be null
		if ($svn_add_param =~ m/^\s*\?\s+(.*)/) {
			#$1 contains the file name
			system("svn add $1");
		}
	}# while(my $svn_add_param = <CMD>)
	close CMD;
	#Create the build tag depending on the build_type
	if($build_type eq "baseline"){
		$rel_tag = "base" . $build_number;	
	} elsif ($build_type eq "cron"){
		$rel_tag = "cron" . $build_number;
	}	
	$svn_path = $svn_path . "/tags/$rel_tag";
	#Create the build folder in the repository
	system "svn mkdir -m \"Making the tag folder for the build\" $svn_path";

	#Copy all files/folders
	open(DIR, "ls|");
	my $line;
	while($line = <DIR>){
		chomp($line);
		system "svn copy -m \"Build Tag\" $line $svn_path ";
	}
	close DIR;
	#Go back the build tool directory
	chdir($build_tool_directory);
	
}

1;

